﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SeaBattle.Domain.Abstract;

namespace SeaBattle.Domain.Entities
{
    public class Game
    {
        public Game(int id, DateTime created, Player creator, IShipRepository shipRepository, IFleetRepository fleetRepository,IPlayerRepository playerRepository)
        {
            Id = id;
            Created = created;
            Creator = creator;
            State = GameState.STATE_CREATED;
            this.FleetRepository = fleetRepository;
            this.ShipRepository = shipRepository;
            this.PlayerRepository = playerRepository;
        }

        private void InitializeFleet(Player player)
        {

        }

        private Player opponent;

        public int Id { get; private set; }

        public int Preset { get; set; }

        /// <summary>
        /// Gets the created.
        /// </summary>
        public DateTime Created { get; private set; }

        /// <summary>
        /// Gets the creator.
        /// </summary>
        public Player Creator { get; private set; }

        /// <summary>
        /// Gets or sets the opponent.
        /// </summary>
        /// <value>
        /// The opponent.
        /// </value>
        public Player Opponent { get { return opponent; } set { SetOpponent(value); } }

        public GameState State { get; private set; }

        public bool Opened
        {
            get { return State == GameState.STATE_OPENED; }
            set
            {
                // Check 
                // Nop
                // Change real state
                if (value)
                {
                    State = GameState.STATE_OPENED;
                }
            }
        }

        public bool Closed
        {
            get { return State == GameState.STATE_CLOSED; }
            set
            {
                // Check 
                // Nop
                // Change real state
                if (value)
                {
                    State = GameState.STATE_CLOSED;
                }
            }
        }

        public bool BoardPreparing
        {
            get { return State == GameState.STATE_BOARD_SETUP; }
            set
            {
                // Check 
                // Nop
                // Change real state
                if (value)
                {
                    State = GameState.STATE_BOARD_SETUP;
                }
            }
        }

        private IShipRepository ShipRepository;

        private IFleetRepository FleetRepository;

        private IPlayerRepository PlayerRepository;


        private void SetOpponent(Player theOpponent)
        {
            // The game must be in Opened status
            if (!Opened)
            {
                throw new Exception("The game " + Id + " not opened");
            }
            // Check whether Creator and Opponent are not the same persons
            if (Creator == theOpponent)
            {
                throw new Exception("The opponent is the same as creator of the game " + Id);
            }
            // Set opponent
            opponent = theOpponent;
        }

        public void JoinOpponent(Player theOpponent)
        {
            Opponent = theOpponent;
            BoardPreparing = true;
        }

 

        private Dictionary<Player, Fleet> Navies;

        public Dictionary<Player, Fleet> GetNavies
        {
            get
            {
                return Navies;
            }
        }

        public Ship AddShip(Player player,int x,int y,int partsCount,ShipOrientation orientation)
        {
            if (!BoardPreparing)
                throw new Exception("The game is not in preparing state.");
            if (!Navies.ContainsKey(player))
                throw new Exception("There is no such player.");
            Ship newShip = ShipRepository.CreateShip(partsCount);
            Navies[player].AddShip(newShip, orientation);
            return newShip;
        }

        public bool RemoveShip(int id_ship)
        {
            if (Navies[Creator].HasShip(id_ship))
            {
                Navies[Creator].RemoveShip(id_ship);
                ShipRepository.RemoveShip(id_ship);
            }
            else
                if (Navies[Opponent].HasShip(id_ship))
                {
                    Navies[Creator].RemoveShip(id_ship);
                    ShipRepository.RemoveShip(id_ship);
                }
                else
                    return false;
            return true;
        }

        public void ResetFleet(int id_player)
        {
            if (PlayerRepository.GetPlayer(id_player) == Opponent)
                Navies[Opponent].ResetFleet();
            else
                if (PlayerRepository.GetPlayer(id_player) == Creator)
                    Navies[Creator].ResetFleet();
                else
                    throw new Exception("This player is not belong to this game!");
        }

    }

    public enum GameState
    {
        STATE_CREATED = 0,
        STATE_GAME_SETUP,
        STATE_OPENED,
        STATE_BOARD_SETUP, // Setup game board
        STATE_PLAY,
        STATE_PAUSE,
        STATE_CLOSED
    }
}
